import {
  BaseSymbol,
  IntegerSymbol,
  RealSymbol,
  FunctionSymbol,
  ProcedureSymbol,
  StringSymbol,
  VectorSymbol,
  FunctionArgument,
} from "./PL00Symbols";
import { PL00SymbolTable } from "./PL00SymbolTable";
class PL00SymbolCalculator {
  visitor: any;
  symbolTable: PL00SymbolTable;
  /**
   * 注入访问器和符号表
   * @param visitor 访问器
   * @param symbolTable 符号表
   */
  constructor(visitor: any, symbolTable: PL00SymbolTable) {
    this.visitor = visitor;
    this.symbolTable = symbolTable;
  }
  /**
   * 加法
   * @param x 左符号
   * @param y 右符号
   * @returns 运算结果
   */
  Add(x: BaseSymbol, y: BaseSymbol): BaseSymbol {
    if (x.type === "Integer") {
      if (y.type === "Integer") {
        return new IntegerSymbol(x.value + y.value);
      } else if (y.type === "Real") {
        return new RealSymbol(x.value + y.value);
      }
    } else if (x.type === "Real") {
      if (y.type === "Integer" || y.type === "Real") {
        return new RealSymbol(x.value + y.value);
      }
    }
    if (x.type === "String" || y.type === "String") {
      return new StringSymbol(
        this.visitor.callFunction("toStr", [x])?.value +
          this.visitor.callFunction("toStr", [y])?.value
      );
    }
    return this.visitor.callFunction("add", [x, y]);
  }
  /**
   * 减法
   * @param x 左符号
   * @param y 右符号
   * @returns 运算结果
   */
  Sub(x: BaseSymbol, y: BaseSymbol): BaseSymbol {
    if (x.type === "Integer") {
      if (y.type === "Integer") {
        return new IntegerSymbol(x.value - y.value);
      } else if (y.type == "Real") {
        return new RealSymbol(x.value - y.value);
      }
    } else if (x.type === "Real") {
      if (y.type === "Integer" || y.type == "Real") {
        return new RealSymbol(x.value - y.value);
      }
    } else {
      return this.visitor.callFunction("sub", [x, y]);
    }
  }
  /**
   * 乘法
   * @param x 左符号
   * @param y 右符号
   * @returns 运算结果
   */
  Multiply(x: BaseSymbol, y: BaseSymbol): BaseSymbol {
    if (x.type === "Integer") {
      if (y.type === "Integer") {
        return new IntegerSymbol(x.value * y.value);
      } else if (y.type === "Real") {
        return new RealSymbol(x.value * y.value);
      }
    } else if (x.type === "Real") {
      if (y.type === "Integer" || y.type === "Real") {
        return new RealSymbol(x.value * y.value);
      }
    } else {
      return this.visitor.callFunction("mul", [x, y]);
    }
  }
  /**
   * 除法
   * @param x 左符号
   * @param y 右符号
   * @returns 运算结果
   */
  Divide(x: BaseSymbol, y: BaseSymbol): BaseSymbol {
    // 并没有特殊处理喜闻乐见的除以0情况
    if (x.type === "Integer") {
      if (y.type === "Integer") {
        return new IntegerSymbol(Math.trunc(x.value / y.value));
      } else if (y.type === "Real") {
        return new RealSymbol(x.value / y.value);
      }
    } else if (x.type === "Real") {
      if (y.type === "Integer" || y.type === "Real") {
        return new RealSymbol(x.value / y.value);
      }
    } else {
      return this.visitor.callFunction("div", [x, y]);
    }
  }
}

export { PL00SymbolCalculator };
